<template>
    <main>
        <div class="menu" editor-component="menu">
      <div class="menu-item">
        <div class="menu-item__undo">
          <i></i>
        </div>
        <div class="menu-item__redo">
          <i></i>
        </div>
        <div class="menu-item__painter" title="格式刷(双击可连续使用)">
          <i></i>
        </div>
        <div class="menu-item__format" title="清除格式">
          <i></i>
        </div>
      </div>
      <div class="menu-divider"></div>
      <div class="menu-item">
        <div class="menu-item__font">
          <span class="select" title="字体">微软雅黑</span>
          <div class="options">
            <ul>
              <li data-family="Microsoft YaHei" style="font-family:'Microsoft YaHei';">微软雅黑</li>
              <li data-family="华文宋体" style="font-family:'华文宋体';">华文宋体</li>
              <li data-family="华文黑体" style="font-family:'华文黑体';">华文黑体</li>
              <li data-family="华文仿宋" style="font-family:'华文仿宋';">华文仿宋</li>
              <li data-family="华文楷体" style="font-family:'华文楷体';">华文楷体</li>
              <li data-family="华文琥珀" style="font-family:'华文琥珀';">华文琥珀</li>
              <li data-family="华文楷体" style="font-family:'华文楷体';">华文楷体</li>
              <li data-family="华文隶书" style="font-family:'华文隶书';">华文隶书</li>
              <li data-family="华文新魏" style="font-family:'华文新魏';">华文新魏</li>
              <li data-family="华文行楷" style="font-family:'华文行楷';">华文行楷</li>
              <li data-family="华文中宋" style="font-family:'华文中宋';">华文中宋</li>
              <li data-family="华文彩云" style="font-family:'华文彩云';">华文彩云</li>
              <li data-family="Arial" style="font-family:'Arial';">Arial</li>
              <li data-family="Segoe UI" style="font-family:'Segoe UI';">Segoe UI</li>
              <li data-family="Ink Free" style="font-family:'Ink Free';">Ink Free</li>
              <li data-family="Fantasy" style="font-family:'Fantasy';">Fantasy</li>
            </ul>
          </div>
        </div>
        <div class="menu-item__size">
          <span class="select" title="字体">小四</span>
          <div class="options">
            <ul>
              <li data-size="56">初号</li>
              <li data-size="48">小初</li>
              <li data-size="34">一号</li>
              <li data-size="32">小一</li>
              <li data-size="29">二号</li>
              <li data-size="24">小二</li>
              <li data-size="21">三号</li>
              <li data-size="20">小三</li>
              <li data-size="18">四号</li>
              <li data-size="16">小四</li>
              <li data-size="14">五号</li>
              <li data-size="12">小五</li>
              <li data-size="10">六号</li>
              <li data-size="8">小六</li>
              <li data-size="7">七号</li>
              <li data-size="6">八号</li>
            </ul>
          </div>
        </div>
        <div class="menu-item__size-add">
          <i></i>
        </div>
        <div class="menu-item__size-minus">
          <i></i>
        </div>
        <div class="menu-item__bold">
          <i></i>
        </div>
        <div class="menu-item__italic">
          <i></i>
        </div>
        <div class="menu-item__underline">
          <i></i>
          <span class="select"></span>
          <div class="options">
            <ul>
              <li data-decoration-style='solid'>
                <i></i>
              </li>
              <li data-decoration-style='double'>
                <i></i>
              </li>
              <li data-decoration-style='dashed'>
                <i></i>
              </li>
              <li data-decoration-style='dotted'>
                <i></i>
              </li>
              <li data-decoration-style='wavy'>
                <i></i>
              </li>
            </ul>
          </div>
        </div>
        <div class="menu-item__strikeout" title="删除线(Ctrl+Shift+X)">
          <i></i>
        </div>
        <div class="menu-item__superscript">
          <i></i>
        </div>
        <div class="menu-item__subscript">
          <i></i>
        </div>
        <div class="menu-item__color" title="字体颜色">
          <i></i>
          <span></span>
          <input type="color" id="color" />
        </div>
        <div class="menu-item__highlight" title="高亮">
          <i></i>
          <span></span>
          <input type="color" id="highlight">
        </div>
      </div>
      <div class="menu-divider"></div>
      <div class="menu-item">
        <div class="menu-item__title">
          <i></i>
          <span class="select" title="切换标题">正文</span>
          <div class="options">
            <ul>
              <li style="font-size:16px;">正文</li>
              <li data-level="first" style="font-size:26px;">标题1</li>
              <li data-level="second" style="font-size:24px;">标题2</li>
              <li data-level="third" style="font-size:22px;">标题3</li>
              <li data-level="fourth" style="font-size:20px;">标题4</li>
              <li data-level="fifth" style="font-size:18px;">标题5</li>
              <li data-level="sixth" style="font-size:16px;">标题6</li>
            </ul>
          </div>
        </div>
        <div class="menu-item__left">
          <i></i>
        </div>
        <div class="menu-item__center">
          <i></i>
        </div>
        <div class="menu-item__right">
          <i></i>
        </div>
        <div class="menu-item__alignment">
          <i></i>
        </div>
        <div class="menu-item__justify">
          <i></i>
        </div>
        <div class="menu-item__row-margin">
          <i title="行间距"></i>
          <div class="options">
            <ul>
              <li data-rowmargin='1'>1</li>
              <li data-rowmargin="1.25">1.25</li>
              <li data-rowmargin="1.5">1.5</li>
              <li data-rowmargin="1.75">1.75</li>
              <li data-rowmargin="2">2</li>
              <li data-rowmargin="2.5">2.5</li>
              <li data-rowmargin="3">3</li>
            </ul>
          </div>
        </div>
        <div class="menu-item__list">
          <i></i>
          <div class="options">
            <ul>
              <li>
                <label>取消列表</label>
              </li>
              <li data-list-type="ol" data-list-style='decimal'>
                <label>有序列表：</label>
                <ol>
                  <li>________</li>
                </ol>
              </li>
              <li data-list-type="ul" data-list-style='checkbox'>
                <label>复选框列表：</label>
                <ul style="list-style-type: '☑️ ';">
                  <li>________</li>
                </ul>
              </li>
              <li data-list-type="ul" data-list-style='disc'>
                <label>实心圆点列表：</label>
                <ul style="list-style-type: disc;">
                  <li>________</li>
                </ul>
              </li>
              <li data-list-type="ul" data-list-style='circle'>
                <label>空心圆点列表：</label>
                <ul style="list-style-type: circle;">
                  <li>________</li>
                </ul>
              </li>
              <li data-list-type="ul" data-list-style='square'>
                <label>空心方块列表：</label>
                <ul style="list-style-type: '☐ ';">
                  <li>________</li>
                </ul>
              </li>
            </ul>
          </div>
        </div>
      </div>
      <div class="menu-divider"></div>
      <div class="menu-item">
        <div class="menu-item__table">
          <i title="表格"></i>
        </div>
        <div class="menu-item__table__collapse">
          <div class="table-close">×</div>
          <div class="table-title">
            <span class="table-select">插入</span>
            <span>表格</span>
          </div>
          <div class="table-panel"></div>
        </div>
        <div class="menu-item__image">
          <i title="图片"></i>
          <input type="file" id="image" accept=".png, .jpg, .jpeg, .svg, .gif">
        </div>
        <div class="menu-item__hyperlink">
          <i title="超链接"></i>
        </div>
        <div class="menu-item__separator">
          <i title="分割线"></i>
          <div class="options">
            <ul>
              <li data-separator='0,0'>
                <i></i>
              </li>
              <li data-separator="1,1">
                <i></i>
              </li>
              <li data-separator="3,1">
                <i></i>
              </li>
              <li data-separator="4,4">
                <i></i>
              </li>
              <li data-separator="7,3,3,3">
                <i></i>
              </li>
              <li data-separator="6,2,2,2,2,2">
                <i></i>
              </li>
            </ul>
          </div>
        </div>
        <div class="menu-item__watermark">
          <i title="水印(添加、删除)"></i>
          <div class="options">
            <ul>
              <li data-menu="add">添加水印</li>
              <li data-menu="delete">删除水印</li>
            </ul>
          </div>
        </div>
        <div class="menu-item__codeblock" title="代码块">
          <i></i>
        </div>
        <div class="menu-item__page-break" title="分页符">
          <i></i>
        </div>
        <div class="menu-item__control">
          <i title="控件"></i>
          <div class="options">
            <ul>
              <li data-control='text'>文本</li>
              <li data-control="number">数值</li>
              <li data-control="select">列举</li>
              <li data-control="date">日期</li>
              <li data-control="checkbox">复选框</li>
              <li data-control="radio">单选框</li>
            </ul>
          </div>
        </div>
        <div class="menu-item__checkbox" title="复选框">
          <i></i>
        </div>
        <div class="menu-item__radio" title="单选框">
          <i></i>
        </div>
        <div class="menu-item__latex" title="LateX">
          <i></i>
        </div>
        <div class="menu-item__date">
          <i title="日期"></i>
          <div class="options">
            <ul>
              <li data-format="yyyy-MM-dd"></li>
              <li data-format="yyyy-MM-dd hh:mm:ss"></li>
            </ul>
          </div>
        </div>
        <div class="menu-item__block" title="内容块">
          <i></i>
        </div>
      </div>
      <div class="menu-divider"></div>
      <div class="menu-item">
        <div class="menu-item__search" data-menu="search">
          <i></i>
        </div>
        <div class="menu-item__search__collapse" data-menu="search">
          <div class="menu-item__search__collapse__search">
            <input type="text" />
            <label class="search-result"></label>
            <div class="arrow-left">
              <i></i>
            </div>
            <div class="arrow-right">
              <i></i>
            </div>
            <span>×</span>
          </div>
          <div class="menu-item__search__collapse__replace">
            <input type="text">
            <button>替换</button>
          </div>
        </div>
        <div class="menu-item__print" data-menu="print">
          <i></i>
        </div>
      </div>
    </div>
      <div class="editor"></div>
      <input type="file" name="file-docx" id="file-docx" accept=".docx" />
      <!-- <input type="file" name="file-excel" id="file-excel" accept=".xlsx" /> -->
    </main>
  </template>
  
  <script setup lang="ts">
  import { onMounted } from "vue";
  import { BlockType, ControlType, Editor, ElementType, ListStyle, RowFlex, TextDecorationStyle, TitleLevel, type IBlock, type IElement } from "@hufe921/canvas-editor";
//   import barcode1dPlugin from "@hufe921/canvas-editor-plugin-barcode1d";
//   import barcode2dPlugin from "@hufe921/canvas-editor-plugin-barcode2d";
//   import codeblockPlugin from "@hufe921/canvas-editor-plugin-codeblock";
  import docxPlugin from "@hufe921/canvas-editor-plugin-docx";
//   import excelPlugin from "@hufe921/canvas-editor-plugin-excel";
  import floatingToolbarPlugin from "@hufe921/canvas-editor-plugin-floating-toolbar";
  import prism from 'prismjs'
  import htmlToRtf from '../utils/html-to-rtf';

// import { rtfArrayBufferToDocx } from "../utils";

// import * as shiva from 'shiva-wasm';

  import { formatPrismToken } from './utils/prism'
  // import { debounce, nextTick, scrollIntoView } from './utils'

  import { Dialog } from './dialog/Dialog'

import type { ListType } from "quill-delta-to-html";

//   import diagramPlugin from "@hufe921/canvas-editor-plugin-diagram";
//   import casePlugin from "@hufe921/canvas-editor-plugin-case";
  
  onMounted(() => {
    // @ts-ignore
    const instance = new Editor(document.querySelector(".editor"), {
      main: [
    {
        "value": "",
        "type": "image",
        "width": 27,
        "height": 18,
        "id": "45e498e8-ca48-4c77-7271-bf1282e50d49"
    },
    {
        "value": "\n",
        "size": 16,
        "bold": false,
        "color": "rgb(33, 53, 71)",
        "italic": false
    },
    {
        "value": "",
        "type": "title",
        "valueList": [
            {
                "value": "AAA等待",
                "size": 16,
                "bold": false,
                "color": "rgb(33, 53, 71)",
                "italic": false
            }
        ],
        "level": "second"
    },
    {
        "value": "\n",
        "type": "table",
        "trList": [
            {
                "height": 42,
                "tdList": [
                    {
                        "colspan": 1,
                        "rowspan": 1,
                        "value": [
                            {
                                "value": "a",
                                "size": 16,
                                "bold": false,
                                "color": "rgb(33, 53, 71)",
                                "italic": false
                            }
                        ]
                    },
                    {
                        "colspan": 2,
                        "rowspan": 1,
                        "value": [
                            {
                                "value": "3r",
                                "size": 16,
                                "bold": false,
                                "color": "rgb(33, 53, 71)",
                                "italic": false
                            }
                        ]
                    }
                ],
                "minHeight": 42
            },
            {
                "height": 42,
                "tdList": [
                    {
                        "colspan": 1,
                        "rowspan": 1,
                        "value": [
                            {
                                "value": "e",
                                "size": 16,
                                "bold": false,
                                "color": "rgb(33, 53, 71)",
                                "italic": false
                            }
                        ]
                    },
                    {
                        "colspan": 1,
                        "rowspan": 1,
                        "value": [
                            {
                                "value": "e",
                                "size": 16,
                                "bold": false,
                                "color": "rgb(33, 53, 71)",
                                "italic": false
                            }
                        ]
                    },
                    {
                        "colspan": 1,
                        "rowspan": 1,
                        "value": [
                            {
                                "value": "q",
                                "size": 16,
                                "bold": false,
                                "color": "rgb(33, 53, 71)",
                                "italic": false
                            }
                        ]
                    }
                ],
                "minHeight": 42
            }
        ],
        "width": 555,
        "height": 84,
        "colgroup": [
            {
                "width": 185
            },
            {
                "width": 185
            },
            {
                "width": 185
            }
        ],
        "id": "513f68fa-f661-81a1-8840-dee8d671eaae"
    },
    {
        "value": "\n"
    },
    {
        "value": "asdd",
        "size": 16,
        "bold": false,
        "color": "rgb(33, 53, 71)",
        "italic": false
    },
    {
        "value": "\n"
    },
    {
        "value": "asdfasdfasdfasdf",
        "size": 16,
        "bold": false,
        "color": "rgb(33, 53, 71)",
        "italic": false
    }
],
      },
      {
          "mode": "edit",
        "defaultType": "TEXT",
        "defaultColor": "#000000",
        "defaultFont": "Microsoft YaHei",
        "defaultSize": 16,
        "minSize": 5,
        "maxSize": 72,
        "defaultRowMargin": 1,
        "defaultBasicRowMarginHeight": 8,
        "defaultTabWidth": 32,
        "width": 794,
        "height": 1123,
        "scale": 1,
        "pageGap": 20,
        "underlineColor": "#000000",
        "strikeoutColor": "#FF0000",
        "rangeAlpha": 0.6,
        "rangeColor": "#AECBFA",
        "rangeMinWidth": 5,
        "searchMatchAlpha": 0.6,
        "searchMatchColor": "#FFFF00",
        "searchNavigateMatchColor": "#AAD280",
        "highlightAlpha": 0.6,
        "resizerColor": "#4182D9",
        "resizerSize": 5,
        "marginIndicatorSize": 35,
        "marginIndicatorColor": "#BABABA",
        "margins": [
          100,
          120,
          100,
          120
        ],
        "pageMode": "paging",
        "renderMode": "speed",
        "defaultHyperlinkColor": "#0000FF",
        "paperDirection": "vertical",
        "inactiveAlpha": 0.6,
        "historyMaxRecordCount": 100,
        "wordBreak": "break-word",
        "printPixelRatio": 3,
        "maskMargin": [
          60,
          0,
          30,
          0
        ],
        "letterClass": [
          "A-Za-z"
        ],
        "contextMenuDisableKeys": [],
        "scrollContainerSelector": "",
        "watermark": {
          "data": "CANVAS-EDITOR",
          "color": "#AEB5C0",
          "opacity": 0.3,
          "size": 120,
          "font": "Microsoft YaHei",
          "repeat": false,
          "gap": [
            10,
            10
          ]
        },
        "pageNumber": {
          "bottom": 60,
          "size": 12,
          "font": "Microsoft YaHei",
          "color": "#000000",
          "rowFlex": "center",
          "format": "第{pageNo}页/共{pageCount}页",
          "numberType": "arabic",
          "disabled": false,
          "startPageNo": 1,
          "fromPageNo": 0,
          "maxPageNo": null
        },
        "placeholder": {
          "data": "请输入正文",
          "color": "#DCDFE6",
          "opacity": 1,
          "size": 16,
          "font": "Microsoft YaHei"
        },
        "zone": {
          "tipDisabled": false
        },
        "table": {
          "tdPadding": [
            0,
            5,
            5,
            5
          ],
          "defaultTrMinHeight": 42,
          "defaultColMinWidth": 40,
          "defaultBorderColor": "#000000"
        },
        "header": {
          "top": 30,
          "maxHeightRadio": "half",
          "disabled": false,
          "editable": true
        },
        "footer": {
          "bottom": 30,
          "maxHeightRadio": "half",
          "disabled": false,
          "editable": true
        },
        "control": {
          "placeholderColor": "#9c9b9b",
          "bracketColor": "#000000",
          "prefix": "{",
          "postfix": "}",
          "borderWidth": 1,
          "borderColor": "#000000",
          "activeBackgroundColor": ""
        },
        "checkbox": {
          "width": 14,
          "height": 14,
          "gap": 5,
          "lineWidth": 1,
          "fillStyle": "#5175f4",
          "strokeStyle": "#ffffff",
          "verticalAlign": "bottom"
        },
        "radio": {
          "width": 14,
          "height": 14,
          "gap": 5,
          "lineWidth": 1,
          "fillStyle": "#5175f4",
          "strokeStyle": "#000000",
          "verticalAlign": "bottom"
        },
        "cursor": {
          "width": 1,
          "color": "#000000",
          "dragWidth": 2,
          "dragColor": "#0000FF"
        },
        "title": {
          "defaultFirstSize": 26,
          "defaultSecondSize": 24,
          "defaultThirdSize": 22,
          "defaultFourthSize": 20,
          "defaultFifthSize": 18,
          "defaultSixthSize": 16
        },
        "group": {
          "opacity": 0.1,
          "backgroundColor": "#E99D00",
          "activeOpacity": 0.5,
          "activeBackgroundColor": "#E99D00",
          "disabled": false
        },
        "pageBreak": {
          "font": "Microsoft YaHei",
          "fontSize": 12,
          "lineDash": [
            3,
            1
          ]
        },
        "background": {
          "color": "#FFFFFF",
          "image": "",
          "size": "cover",
          "repeat": "no-repeat",
          "applyPageNumbers": []
        },
        "lineBreak": {
          "disabled": true,
          "color": "#CCCCCC",
          "lineWidth": 1.5
        },
        "separator": {
          "lineWidth": 1,
          "strokeStyle": "#000000"
        },
        "lineNumber": {
          "size": 12,
          "font": "Microsoft YaHei",
          "color": "#000000",
          "disabled": true,
          "right": 20,
          "type": "continuity"
        },
        "pageBorder": {
          "color": "#000000",
          "lineWidth": 1,
          "padding": [
            0,
            5,
            0,
            5
          ],
          "disabled": true
        },
        "badge": {
          "top": 0,
          "left": 5
        },
      }
    );

    // @ts-ignore
    window._editor=instance;
  
    // instance.use(barcode1dPlugin);
    // instance.use(barcode2dPlugin);
    // instance.use(codeblockPlugin);
    instance.use(docxPlugin);
    // instance.use(excelPlugin);
    instance.use(floatingToolbarPlugin);
    // instance.use(diagramPlugin);
    // instance.use(casePlugin);
  
    const docxFileInput = document.querySelector("#file-docx");
    // const excelFileInput = document.querySelector("#file-excel");
  
    instance.register.contextMenuList([
    //   {
    //     name: "插入条形码",
    //     when: (payload) => {
    //       return !payload.isReadonly && payload.editorTextFocus;
    //     },
    //     callback: (command) => {
    //       const content = window.prompt("请输入内容");
    //       command.executeInsertBarcode1D(content, 200, 100);
    //     },
    //   },
    //   {
    //     name: "插入二维码",
    //     when: (payload) => {
    //       return !payload.isReadonly && payload.editorTextFocus;
    //     },
    //     callback: (command) => {
    //       const content = window.prompt("请输入内容");
    //       command.executeInsertBarcode2D(content, 200, 200);
    //     },
    //   },
    //   {
    //     name: "插入代码块",
    //     when: (payload) => {
    //       return !payload.isReadonly && payload.editorTextFocus;
    //     },
    //     callback: (command) => {
    //       const content = window.prompt("请输入内容");
    //       command.executeInsertCodeblock(content);
    //     },
    //   },
     
      {
        name: "导出Rtf",
        when: (payload) => true,
        callback: (command) => {
          const htmlStr = command.getHTML().main;
          // const cfg = {};
    // console.log(html);
    const rtfContent = htmlToRtf(htmlStr);
    // from here on, works only on htmlStr
    const blob = new Blob([rtfContent], { type: "application/rtf;charset=utf-8" });
    const blobURL = window.URL.createObjectURL(blob);
    const fileName = 'save.rtf';
    const tempLink = document.createElement('a');
    tempLink.style.display = 'none';
    tempLink.href = blobURL;
    const downloadName = decodeURIComponent(fileName);
    tempLink.setAttribute('download', downloadName);
    tempLink.download = downloadName;
    // alert(decodeURIComponent(fileName));
    // 兼容：某些浏览器不支持HTML5的download属性
    if (typeof tempLink.download === 'undefined') {
      tempLink.setAttribute('target', '_blank');
    }
    // 挂载a标签
    document.body.appendChild(tempLink);
    tempLink.click();
    setTimeout(() => {
      document.body.removeChild(tempLink);
      // 释放blob URL地址
      window.URL.revokeObjectURL(blobURL);
    }, 3000);
          // command.executeExportDocx({
          //   fileName: "canvas-editor",
          // });
        },
      },
      // {
      //   name: "导入RTF",
      //   when: (payload) => true,
      //   callback: async (command) => {
      //     const importRtfFile = async () => {
      //       return new Promise((resolve, reject) => {
      //           // let rtfTextContent = '';
      //           // 创建 input 元素
      //           const input = document.createElement('input');
      //           input.type = 'file';
      //           input.accept = '.rtf';
      //           let isOpenFile = false;
      //           // 监听文件选择事件
      //           input.onchange = async (event) => {
      //             // @ts-ignore
      //               const file = event.target.files[0];
      //               if (file) {
      //                   isOpenFile = true;
      //                   // 读取文件内容
      //                   const reader = new FileReader();
      //                   reader.onload = (e) => {
      //             // @ts-ignore
      //                       const ab = e.target.result;
      //                       // 当文件读取完成后，调用 resolve 函数将结果传递出去
      //                       resolve({
      //                         name: file.name,
      //             // @ts-ignore
      //                         arrayBuffer: new Uint8Array(ab)
      //                       });
      //                   };
      //                   reader.onerror = (error) => {
      //                       // 如果文件读取出现错误，调用 reject 函数
      //                       reject(error);
      //                   };
      //                   reader.readAsArrayBuffer(file);
      //               }
      //           };
      //           // 取消事件
      //           window.addEventListener(
      //               'focus',
      //               () => {
      //                   setTimeout(() => {
      //                       if (!isOpenFile) {
      //                           // 取消逻辑处理
      //                           reject(new Error('User cancelled file selection'));
      //                       }
      //                   }, 300);
      //               },
      //               { once: true }
      //           );

      //           // 触发文件选择对话框
      //           input.click();
      //       });
      //     };

      //     const rtfAb: any = await importRtfFile();

      //     const docData = await rtfArrayBufferToDocx(rtfAb.arrayBuffer);

          
      //     // await shiva.default('/shiva_wasm_bg.wasm');

      //     //   // await shiva.initSync();

      //     //   const docData = shiva.convert(rtfAb.arrayBuffer, shiva.FileFormat.Rtf, shiva.FileFormat.Docx);

      //     instance.command.executeImportDocx({
      //       arrayBuffer: docData,
      //     });
      //   },
      // },
    //  {
    //     name: "导出Word",
    //     when: (payload) => true,
    //     callback: (command) => {
    //       command.executeExportDocx({
    //         fileName: "canvas-editor",
    //       });
    //     },
    //   },
    //   {
    //     name: "导入Word",
    //     when: (payload) => true,
    //     callback: (command) => {
    //       docxFileInput.click();
    //     },
    //   },
    //   {
    //     name: "导入excel",
    //     when: (payload) => true,
    //     callback: (command) => {
    //       excelFileInput.click();
    //     },
    //   },
    //   {
    //     name: "打开/编辑流程图",
    //     when: (payload) => {
    //       return !payload.isReadonly && payload.editorTextFocus;
    //     },
    //     callback: (command, context) => {
    //       const extension = context.startElement?.extension;
    //       const data = extension?.name === "diagram" ? extension.xml : "";
    //       command.executeLoadDiagram({
    //         data,
    //         onDestroy: (message) => {
    //           if (!message || !message.data) return;
    //           const { bounds } = message;
    //           if (!data) {
    //             // 新增
    //             command.executeInsertElementList([
    //               {
    //                 type: ElementType.IMAGE,
    //                 width: bounds.width,
    //                 height: bounds.height,
    //                 value: message.data,
    //                 extension: {
    //                   name: "diagram",
    //                   xml: message.xml,
    //                 },
    //               },
    //             ]);
    //           } else {
    //             // 更新
    //             command.executeUpdateElementById({
    //               id: context.startElement.id,
    //               properties: {
    //                 width: bounds.width,
    //                 height: bounds.height,
    //                 value: message.data,
    //                 extension: {
    //                   name: "diagram",
    //                   xml: message.xml,
    //                 },
    //               },
    //             });
    //           }
    //         },
    //       });
    //     },
    //   },
    //   {
    //     name: "转成大写",
    //     when: (payload) => {
    //       return !payload.isReadonly && payload.editorHasSelection;
    //     },
    //     callback: (command) => {
    //       command.executeUpperCase();
    //     },
    //   },
    //   {
    //     name: "转成小写",
    //     when: (payload) => {
    //       return !payload.isReadonly && payload.editorHasSelection;
    //     },
    //     callback: (command) => {
    //       command.executeLowerCase();
    //     },
    //   },
    ]);

    const isApple =
    typeof navigator !== 'undefined' && /Mac OS X/.test(navigator.userAgent)
      
    // 2. | 撤销 | 重做 | 格式刷 | 清除格式 |
    const undoDom = document.querySelector<HTMLDivElement>('.menu-item__undo')!
    undoDom.title = `撤销(${isApple ? '⌘' : 'Ctrl'}+Z)`
    undoDom.onclick = function () {
      console.log('undo')
      instance.command.executeUndo()
    }

    const redoDom = document.querySelector<HTMLDivElement>('.menu-item__redo')!
    redoDom.title = `重做(${isApple ? '⌘' : 'Ctrl'}+Y)`
    redoDom.onclick = function () {
      console.log('redo')
      instance.command.executeRedo()
    }

    const painterDom = document.querySelector<HTMLDivElement>(
      '.menu-item__painter'
    )!

    let isFirstClick = true
    let painterTimeout: number
    painterDom.onclick = function () {
      if (isFirstClick) {
        isFirstClick = false
        painterTimeout = window.setTimeout(() => {
          console.log('painter-click')
          isFirstClick = true
          instance.command.executePainter({
            isDblclick: false
          })
        }, 200)
      } else {
        window.clearTimeout(painterTimeout)
      }
    }

    painterDom.ondblclick = function () {
      console.log('painter-dblclick')
      isFirstClick = true
      window.clearTimeout(painterTimeout)
      instance.command.executePainter({
        isDblclick: true
      })
    }

    document.querySelector<HTMLDivElement>('.menu-item__format')!.onclick =
      function () {
        console.log('format')
        instance.command.executeFormat()
      }

    // 3. | 字体 | 字体变大 | 字体变小 | 加粗 | 斜体 | 下划线 | 删除线 | 上标 | 下标 | 字体颜色 | 背景色 |
    const fontDom = document.querySelector<HTMLDivElement>('.menu-item__font')!
    const fontSelectDom = fontDom.querySelector<HTMLDivElement>('.select')!
    const fontOptionDom = fontDom.querySelector<HTMLDivElement>('.options')!
    fontDom.onclick = function () {
      console.log('font')
      fontOptionDom.classList.toggle('visible')
    }
    fontOptionDom.onclick = function (evt) {
      const li = evt.target as HTMLLIElement
      instance.command.executeFont(li.dataset.family!)
    }

    const sizeSetDom = document.querySelector<HTMLDivElement>('.menu-item__size')!
    const sizeSelectDom = sizeSetDom.querySelector<HTMLDivElement>('.select')!
    const sizeOptionDom = sizeSetDom.querySelector<HTMLDivElement>('.options')!
    sizeSetDom.title = `设置字号`
    sizeSetDom.onclick = function () {
      console.log('size')
      sizeOptionDom.classList.toggle('visible')
    }
    sizeOptionDom.onclick = function (evt) {
      const li = evt.target as HTMLLIElement
      instance.command.executeSize(Number(li.dataset.size!))
    }

    const sizeAddDom = document.querySelector<HTMLDivElement>(
      '.menu-item__size-add'
    )!
    sizeAddDom.title = `增大字号(${isApple ? '⌘' : 'Ctrl'}+[)`
    sizeAddDom.onclick = function () {
      console.log('size-add')
      instance.command.executeSizeAdd()
    }

    const sizeMinusDom = document.querySelector<HTMLDivElement>(
      '.menu-item__size-minus'
    )!
    sizeMinusDom.title = `减小字号(${isApple ? '⌘' : 'Ctrl'}+])`
    sizeMinusDom.onclick = function () {
      console.log('size-minus')
      instance.command.executeSizeMinus()
    }

    const boldDom = document.querySelector<HTMLDivElement>('.menu-item__bold')!
    boldDom.title = `加粗(${isApple ? '⌘' : 'Ctrl'}+B)`
    boldDom.onclick = function () {
      console.log('bold')
      instance.command.executeBold()
    }

    const italicDom =
      document.querySelector<HTMLDivElement>('.menu-item__italic')!
    italicDom.title = `斜体(${isApple ? '⌘' : 'Ctrl'}+I)`
    italicDom.onclick = function () {
      console.log('italic')
      instance.command.executeItalic()
    }

    const underlineDom = document.querySelector<HTMLDivElement>(
      '.menu-item__underline'
    )!
    underlineDom.title = `下划线(${isApple ? '⌘' : 'Ctrl'}+U)`
    const underlineOptionDom =
      underlineDom.querySelector<HTMLDivElement>('.options')!
    underlineDom.querySelector<HTMLSpanElement>('.select')!.onclick =
      function () {
        underlineOptionDom.classList.toggle('visible')
      }
    underlineDom.querySelector<HTMLElement>('i')!.onclick = function () {
      console.log('underline')
      instance.command.executeUnderline()
      underlineOptionDom.classList.remove('visible')
    }
    underlineDom.querySelector<HTMLUListElement>('ul')!.onmousedown = function (
      evt
    ) {
      const li = evt.target as HTMLLIElement
      const decorationStyle = <TextDecorationStyle>li.dataset.decorationStyle
      instance.command.executeUnderline({
        style: decorationStyle
      })
      underlineOptionDom.classList.remove('visible')
    }

    const strikeoutDom = document.querySelector<HTMLDivElement>(
      '.menu-item__strikeout'
    )!
    strikeoutDom.onclick = function () {
      console.log('strikeout')
      instance.command.executeStrikeout()
    }

    const superscriptDom = document.querySelector<HTMLDivElement>(
      '.menu-item__superscript'
    )!
    superscriptDom.title = `上标(${isApple ? '⌘' : 'Ctrl'}+Shift+,)`
    superscriptDom.onclick = function () {
      console.log('superscript')
      instance.command.executeSuperscript()
    }

    const subscriptDom = document.querySelector<HTMLDivElement>(
      '.menu-item__subscript'
    )!
    subscriptDom.title = `下标(${isApple ? '⌘' : 'Ctrl'}+Shift+.)`
    subscriptDom.onclick = function () {
      console.log('subscript')
      instance.command.executeSubscript()
    }

    const colorControlDom = document.querySelector<HTMLInputElement>('#color')!
    colorControlDom.oninput = function () {
      instance.command.executeColor(colorControlDom.value)
    }
    const colorDom = document.querySelector<HTMLDivElement>('.menu-item__color')!
    const colorSpanDom = colorDom.querySelector('span')!
    colorDom.onclick = function () {
      console.log('color')
      colorControlDom.click()
    }

    const highlightControlDom =
      document.querySelector<HTMLInputElement>('#highlight')!
    highlightControlDom.oninput = function () {
      instance.command.executeHighlight(highlightControlDom.value)
    }
    const highlightDom = document.querySelector<HTMLDivElement>(
      '.menu-item__highlight'
    )!
    const highlightSpanDom = highlightDom.querySelector('span')!
    highlightDom.onclick = function () {
      console.log('highlight')
      highlightControlDom?.click()
    }

    const titleDom = document.querySelector<HTMLDivElement>('.menu-item__title')!
    const titleSelectDom = titleDom.querySelector<HTMLDivElement>('.select')!
    const titleOptionDom = titleDom.querySelector<HTMLDivElement>('.options')!
    titleOptionDom.querySelectorAll('li').forEach((li, index) => {
      li.title = `Ctrl+${isApple ? 'Option' : 'Alt'}+${index}`
    })

    titleDom.onclick = function () {
      console.log('title')
      titleOptionDom.classList.toggle('visible')
    }
    titleOptionDom.onclick = function (evt) {
      const li = evt.target as HTMLLIElement
      const level = <TitleLevel>li.dataset.level
      instance.command.executeTitle(level || null)
    }

    const leftDom = document.querySelector<HTMLDivElement>('.menu-item__left')!
    leftDom.title = `左对齐(${isApple ? '⌘' : 'Ctrl'}+L)`
    leftDom.onclick = function () {
      console.log('left')
      instance.command.executeRowFlex(RowFlex.LEFT)
    }

    const centerDom =
      document.querySelector<HTMLDivElement>('.menu-item__center')!
    centerDom.title = `居中对齐(${isApple ? '⌘' : 'Ctrl'}+E)`
    centerDom.onclick = function () {
      console.log('center')
      instance.command.executeRowFlex(RowFlex.CENTER)
    }

    const rightDom = document.querySelector<HTMLDivElement>('.menu-item__right')!
    rightDom.title = `右对齐(${isApple ? '⌘' : 'Ctrl'}+R)`
    rightDom.onclick = function () {
      console.log('right')
      instance.command.executeRowFlex(RowFlex.RIGHT)
    }

    const alignmentDom = document.querySelector<HTMLDivElement>(
      '.menu-item__alignment'
    )!
    alignmentDom.title = `两端对齐(${isApple ? '⌘' : 'Ctrl'}+J)`
    alignmentDom.onclick = function () {
      console.log('alignment')
      instance.command.executeRowFlex(RowFlex.ALIGNMENT)
    }

    const justifyDom = document.querySelector<HTMLDivElement>(
      '.menu-item__justify'
    )!
    justifyDom.title = `分散对齐(${isApple ? '⌘' : 'Ctrl'}+Shift+J)`
    justifyDom.onclick = function () {
      console.log('justify')
      instance.command.executeRowFlex(RowFlex.JUSTIFY)
    }

    const rowMarginDom = document.querySelector<HTMLDivElement>(
      '.menu-item__row-margin'
    )!
    const rowOptionDom = rowMarginDom.querySelector<HTMLDivElement>('.options')!
    rowMarginDom.onclick = function () {
      console.log('row-margin')
      rowOptionDom.classList.toggle('visible')
    }
    rowOptionDom.onclick = function (evt) {
      const li = evt.target as HTMLLIElement
      instance.command.executeRowMargin(Number(li.dataset.rowmargin!))
    }

    const listDom = document.querySelector<HTMLDivElement>('.menu-item__list')!
    listDom.title = `列表(${isApple ? '⌘' : 'Ctrl'}+Shift+U)`
    const listOptionDom = listDom.querySelector<HTMLDivElement>('.options')!
    listDom.onclick = function () {
      console.log('list')
      listOptionDom.classList.toggle('visible')
    }
    listOptionDom.onclick = function (evt) {
      const li = evt.target as HTMLLIElement
      const listType = <ListType>li.dataset.listType || null
      const listStyle = <ListStyle>(<unknown>li.dataset.listStyle)
      instance.command.executeList(listType, listStyle)
    }

    // 4. | 表格 | 图片 | 超链接 | 分割线 | 水印 | 代码块 | 分隔符 | 控件 | 复选框 | LaTeX | 日期选择器
    const tableDom = document.querySelector<HTMLDivElement>('.menu-item__table')!
    const tablePanelContainer = document.querySelector<HTMLDivElement>(
      '.menu-item__table__collapse'
    )!
    const tableClose = document.querySelector<HTMLDivElement>('.table-close')!
    const tableTitle = document.querySelector<HTMLDivElement>('.table-select')!
    const tablePanel = document.querySelector<HTMLDivElement>('.table-panel')!
    // 绘制行列
    const tableCellList: HTMLDivElement[][] = []
    for (let i = 0; i < 10; i++) {
      const tr = document.createElement('tr')
      tr.classList.add('table-row')
      const trCellList: HTMLDivElement[] = []
      for (let j = 0; j < 10; j++) {
        const td = document.createElement('td')
        td.classList.add('table-cel')
        tr.append(td)
        trCellList.push(td)
      }
      tablePanel.append(tr)
      tableCellList.push(trCellList)
    }
    let colIndex = 0
    let rowIndex = 0
    // 移除所有格选择
    function removeAllTableCellSelect() {
      tableCellList.forEach(tr => {
        tr.forEach(td => td.classList.remove('active'))
      })
    }
    // 设置标题内容
    function setTableTitle(payload: string) {
      tableTitle.innerText = payload
    }
    // 恢复初始状态
    function recoveryTable() {
      // 还原选择样式、标题、选择行列
      removeAllTableCellSelect()
      setTableTitle('插入')
      colIndex = 0
      rowIndex = 0
      // 隐藏panel
      tablePanelContainer.style.display = 'none'
    }
    tableDom.onclick = function () {
      console.log('table')
      tablePanelContainer!.style.display = 'block'
    }
    tablePanel.onmousemove = function (evt) {
      const celSize = 16
      const rowMarginTop = 10
      const celMarginRight = 6
      const { offsetX, offsetY } = evt
      // 移除所有选择
      removeAllTableCellSelect()
      colIndex = Math.ceil(offsetX / (celSize + celMarginRight)) || 1
      rowIndex = Math.ceil(offsetY / (celSize + rowMarginTop)) || 1
      // 改变选择样式
      tableCellList.forEach((tr, trIndex) => {
        tr.forEach((td, tdIndex) => {
          if (tdIndex < colIndex && trIndex < rowIndex) {
            td.classList.add('active')
          }
        })
      })
      // 改变表格标题
      setTableTitle(`${rowIndex}×${colIndex}`)
    }
    tableClose.onclick = function () {
      recoveryTable()
    }
    tablePanel.onclick = function () {
      // 应用选择
      instance.command.executeInsertTable(rowIndex, colIndex)
      recoveryTable()
    }

    const imageDom = document.querySelector<HTMLDivElement>('.menu-item__image')!
    const imageFileDom = document.querySelector<HTMLInputElement>('#image')!
    imageDom.onclick = function () {
      imageFileDom.click()
    }
    imageFileDom.onchange = function () {
      const file = imageFileDom.files![0]!
      const fileReader = new FileReader()
      fileReader.readAsDataURL(file)
      fileReader.onload = function () {
        // 计算宽高
        const image = new Image()
        const value = fileReader.result as string
        image.src = value
        image.onload = function () {
          instance.command.executeImage({
            value,
            width: image.width,
            height: image.height
          })
          imageFileDom.value = ''
        }
      }
    }

    const hyperlinkDom = document.querySelector<HTMLDivElement>(
      '.menu-item__hyperlink'
    )!
    hyperlinkDom.onclick = function () {
      console.log('hyperlink')
      new Dialog({
        title: '超链接',
        data: [
          {
            type: 'text',
            label: '文本',
            name: 'name',
            required: true,
            placeholder: '请输入文本',
            value: instance.command.getRangeText()
          },
          {
            type: 'text',
            label: '链接',
            name: 'url',
            required: true,
            placeholder: '请输入链接'
          }
        ],
        onConfirm: payload => {
          const name = payload.find(p => p.name === 'name')?.value
          if (!name) return
          const url = payload.find(p => p.name === 'url')?.value
          if (!url) return
          instance.command.executeHyperlink({
            type: ElementType.HYPERLINK,
            value: '',
            url,
            valueList: splitText(name).map(n => ({
              value: n,
              size: 16
            }))
          })
        }
      })
    }

    const separatorDom = document.querySelector<HTMLDivElement>(
      '.menu-item__separator'
    )!
    const separatorOptionDom =
      separatorDom.querySelector<HTMLDivElement>('.options')!
    separatorDom.onclick = function () {
      console.log('separator')
      separatorOptionDom.classList.toggle('visible')
    }
    separatorOptionDom.onmousedown = function (evt) {
      let payload: number[] = []
      const li = evt.target as HTMLLIElement
      const separatorDash = li.dataset.separator?.split(',').map(Number)
      if (separatorDash) {
        const isSingleLine = separatorDash.every(d => d === 0)
        if (!isSingleLine) {
          payload = separatorDash
        }
      }
      instance.command.executeSeparator(payload)
    }

    const pageBreakDom = document.querySelector<HTMLDivElement>(
      '.menu-item__page-break'
    )!
    pageBreakDom.onclick = function () {
      console.log('pageBreak')
      instance.command.executePageBreak()
    }

    const watermarkDom = document.querySelector<HTMLDivElement>(
      '.menu-item__watermark'
    )!
    const watermarkOptionDom =
      watermarkDom.querySelector<HTMLDivElement>('.options')!
    watermarkDom.onclick = function () {
      console.log('watermark')
      watermarkOptionDom.classList.toggle('visible')
    }
    watermarkOptionDom.onmousedown = function (evt) {
      const li = evt.target as HTMLLIElement
      const menu = li.dataset.menu!
      watermarkOptionDom.classList.toggle('visible')
      if (menu === 'add') {
        new Dialog({
          title: '水印',
          data: [
            {
              type: 'text',
              label: '内容',
              name: 'data',
              required: true,
              placeholder: '请输入内容'
            },
            {
              type: 'color',
              label: '颜色',
              name: 'color',
              required: true,
              value: '#AEB5C0'
            },
            {
              type: 'number',
              label: '字体大小',
              name: 'size',
              required: true,
              value: '120'
            },
            {
              type: 'number',
              label: '透明度',
              name: 'opacity',
              required: true,
              value: '0.3'
            },
            {
              type: 'select',
              label: '重复',
              name: 'repeat',
              value: '0',
              required: false,
              options: [
                {
                  label: '不重复',
                  value: '0'
                },
                {
                  label: '重复',
                  value: '1'
                }
              ]
            },
            {
              type: 'number',
              label: '水平间隔',
              name: 'horizontalGap',
              required: false,
              value: '10'
            },
            {
              type: 'number',
              label: '垂直间隔',
              name: 'verticalGap',
              required: false,
              value: '10'
            }
          ],
          onConfirm: payload => {
            const nullableIndex = payload.findIndex(p => !p.value)
            if (~nullableIndex) return
            const watermark = payload.reduce((pre, cur) => {
              pre[cur.name] = cur.value
              return pre
            }, <any>{})
            const repeat = watermark.repeat === '1'
            instance.command.executeAddWatermark({
              data: watermark.data,
              color: watermark.color,
              size: Number(watermark.size),
              opacity: Number(watermark.opacity),
              repeat,
              gap:
                repeat && watermark.horizontalGap && watermark.verticalGap
                  ? [
                      Number(watermark.horizontalGap),
                      Number(watermark.verticalGap)
                    ]
                  : undefined
            })
          }
        })
      } else {
        instance.command.executeDeleteWatermark()
      }
    }

    const codeblockDom = document.querySelector<HTMLDivElement>(
      '.menu-item__codeblock'
    )!
    codeblockDom.onclick = function () {
      console.log('codeblock')
      new Dialog({
        title: '代码块',
        data: [
          {
            type: 'textarea',
            name: 'codeblock',
            placeholder: '请输入代码',
            width: 500,
            height: 300
          }
        ],
        onConfirm: payload => {
          const codeblock = payload.find(p => p.name === 'codeblock')?.value
          if (!codeblock) return
          const tokenList = prism.tokenize(codeblock, prism.languages.javascript)
          const formatTokenList = formatPrismToken(tokenList)
          const elementList: IElement[] = []
          for (let i = 0; i < formatTokenList.length; i++) {
            const formatToken = formatTokenList[i]
            const tokenStringList = splitText(formatToken.content)
            for (let j = 0; j < tokenStringList.length; j++) {
              const value = tokenStringList[j]
              const element: IElement = {
                value
              }
              if (formatToken.color) {
                element.color = formatToken.color
              }
              if (formatToken.bold) {
                element.bold = true
              }
              if (formatToken.italic) {
                element.italic = true
              }
              elementList.push(element)
            }
          }
          elementList.unshift({
            value: '\n'
          })
          instance.command.executeInsertElementList(elementList)
        }
      })
    }

    const controlDom = document.querySelector<HTMLDivElement>(
      '.menu-item__control'
    )!
    const controlOptionDom = controlDom.querySelector<HTMLDivElement>('.options')!
    controlDom.onclick = function () {
      console.log('control')
      controlOptionDom.classList.toggle('visible')
    }
    controlOptionDom.onmousedown = function (evt) {
      controlOptionDom.classList.toggle('visible')
      const li = evt.target as HTMLLIElement
      const type = <ControlType>li.dataset.control
      switch (type) {
        case ControlType.TEXT:
          new Dialog({
            title: '文本控件',
            data: [
              {
                type: 'text',
                label: '占位符',
                name: 'placeholder',
                required: true,
                placeholder: '请输入占位符'
              },
              {
                type: 'text',
                label: '默认值',
                name: 'value',
                placeholder: '请输入默认值'
              }
            ],
            onConfirm: payload => {
              const placeholder = payload.find(
                p => p.name === 'placeholder'
              )?.value
              if (!placeholder) return
              const value = payload.find(p => p.name === 'value')?.value || ''
              instance.command.executeInsertControl({
                type: ElementType.CONTROL,
                value: '',
                control: {
                  type,
                  value: value
                    ? [
                        {
                          value
                        }
                      ]
                    : null,
                  placeholder
                }
              })
            }
          })
          break
        case ControlType.SELECT:
          new Dialog({
            title: '列举控件',
            data: [
              {
                type: 'text',
                label: '占位符',
                name: 'placeholder',
                required: true,
                placeholder: '请输入占位符'
              },
              {
                type: 'text',
                label: '默认值',
                name: 'code',
                placeholder: '请输入默认值'
              },
              {
                type: 'textarea',
                label: '值集',
                name: 'valueSets',
                required: true,
                height: 100,
                placeholder: `请输入值集JSON，例：\n[{\n"value":"有",\n"code":"98175"\n}]`
              }
            ],
            onConfirm: payload => {
              const placeholder = payload.find(
                p => p.name === 'placeholder'
              )?.value
              if (!placeholder) return
              const valueSets = payload.find(p => p.name === 'valueSets')?.value
              if (!valueSets) return
              const code = payload.find(p => p.name === 'code')?.value
              instance.command.executeInsertControl({
                type: ElementType.CONTROL,
                value: '',
                control: {
                  type,
                  code,
                  value: null,
                  placeholder,
                  valueSets: JSON.parse(valueSets)
                }
              })
            }
          })
          break
        case ControlType.CHECKBOX:
          new Dialog({
            title: '复选框控件',
            data: [
              {
                type: 'text',
                label: '默认值',
                name: 'code',
                placeholder: '请输入默认值，多个值以英文逗号分割'
              },
              {
                type: 'textarea',
                label: '值集',
                name: 'valueSets',
                required: true,
                height: 100,
                placeholder: `请输入值集JSON，例：\n[{\n"value":"有",\n"code":"98175"\n}]`
              }
            ],
            onConfirm: payload => {
              const valueSets = payload.find(p => p.name === 'valueSets')?.value
              if (!valueSets) return
              const code = payload.find(p => p.name === 'code')?.value
              instance.command.executeInsertControl({
                type: ElementType.CONTROL,
                value: '',
                control: {
                  type,
                  code,
                  value: null,
                  valueSets: JSON.parse(valueSets)
                }
              })
            }
          })
          break
        case ControlType.RADIO:
          new Dialog({
            title: '单选框控件',
            data: [
              {
                type: 'text',
                label: '默认值',
                name: 'code',
                placeholder: '请输入默认值'
              },
              {
                type: 'textarea',
                label: '值集',
                name: 'valueSets',
                required: true,
                height: 100,
                placeholder: `请输入值集JSON，例：\n[{\n"value":"有",\n"code":"98175"\n}]`
              }
            ],
            onConfirm: payload => {
              const valueSets = payload.find(p => p.name === 'valueSets')?.value
              if (!valueSets) return
              const code = payload.find(p => p.name === 'code')?.value
              instance.command.executeInsertControl({
                type: ElementType.CONTROL,
                value: '',
                control: {
                  type,
                  code,
                  value: null,
                  valueSets: JSON.parse(valueSets)
                }
              })
            }
          })
          break
        case ControlType.DATE:
          new Dialog({
            title: '日期控件',
            data: [
              {
                type: 'text',
                label: '占位符',
                name: 'placeholder',
                required: true,
                placeholder: '请输入占位符'
              },
              {
                type: 'text',
                label: '默认值',
                name: 'value',
                placeholder: '请输入默认值'
              },
              {
                type: 'select',
                label: '日期格式',
                name: 'dateFormat',
                value: 'yyyy-MM-dd hh:mm:ss',
                required: true,
                options: [
                  {
                    label: 'yyyy-MM-dd hh:mm:ss',
                    value: 'yyyy-MM-dd hh:mm:ss'
                  },
                  {
                    label: 'yyyy-MM-dd',
                    value: 'yyyy-MM-dd'
                  }
                ]
              }
            ],
            onConfirm: payload => {
              const placeholder = payload.find(
                p => p.name === 'placeholder'
              )?.value
              if (!placeholder) return
              const value = payload.find(p => p.name === 'value')?.value || ''
              const dateFormat =
                payload.find(p => p.name === 'dateFormat')?.value || ''
              instance.command.executeInsertControl({
                type: ElementType.CONTROL,
                value: '',
                control: {
                  type,
                  dateFormat,
                  value: value
                    ? [
                        {
                          value
                        }
                      ]
                    : null,
                  placeholder
                }
              })
            }
          })
          break
        case ControlType.NUMBER:
          new Dialog({
            title: '数值控件',
            data: [
              {
                type: 'text',
                label: '占位符',
                name: 'placeholder',
                required: true,
                placeholder: '请输入占位符'
              },
              {
                type: 'text',
                label: '默认值',
                name: 'value',
                placeholder: '请输入默认值'
              }
            ],
            onConfirm: payload => {
              const placeholder = payload.find(
                p => p.name === 'placeholder'
              )?.value
              if (!placeholder) return
              const value = payload.find(p => p.name === 'value')?.value || ''
              instance.command.executeInsertControl({
                type: ElementType.CONTROL,
                value: '',
                control: {
                  type,
                  value: value
                    ? [
                        {
                          value
                        }
                      ]
                    : null,
                  placeholder
                }
              })
            }
          })
          break
        default:
          break
      }
    }

    const checkboxDom = document.querySelector<HTMLDivElement>(
      '.menu-item__checkbox'
    )!
    checkboxDom.onclick = function () {
      console.log('checkbox')
      instance.command.executeInsertElementList([
        {
          type: ElementType.CHECKBOX,
          checkbox: {
            value: false
          },
          value: ''
        }
      ])
    }

    const radioDom = document.querySelector<HTMLDivElement>('.menu-item__radio')!
    radioDom.onclick = function () {
      console.log('radio')
      instance.command.executeInsertElementList([
        {
          type: ElementType.RADIO,
          checkbox: {
            value: false
          },
          value: ''
        }
      ])
    }

    const latexDom = document.querySelector<HTMLDivElement>('.menu-item__latex')!
    latexDom.onclick = function () {
      console.log('LaTeX')
      new Dialog({
        title: 'LaTeX',
        data: [
          {
            type: 'textarea',
            height: 100,
            name: 'value',
            placeholder: '请输入LaTeX文本'
          }
        ],
        onConfirm: payload => {
          const value = payload.find(p => p.name === 'value')?.value
          if (!value) return
          instance.command.executeInsertElementList([
            {
              type: ElementType.LATEX,
              value
            }
          ])
        }
      })
    }

    const dateDom = document.querySelector<HTMLDivElement>('.menu-item__date')!
    const dateDomOptionDom = dateDom.querySelector<HTMLDivElement>('.options')!
    dateDom.onclick = function () {
      console.log('date')
      dateDomOptionDom.classList.toggle('visible')
      // 定位调整
      const bodyRect = document.body.getBoundingClientRect()
      const dateDomOptionRect = dateDomOptionDom.getBoundingClientRect()
      if (dateDomOptionRect.left + dateDomOptionRect.width > bodyRect.width) {
        dateDomOptionDom.style.right = '0px'
        dateDomOptionDom.style.left = 'unset'
      } else {
        dateDomOptionDom.style.right = 'unset'
        dateDomOptionDom.style.left = '0px'
      }
      // 当前日期
      const date = new Date()
      const year = date.getFullYear().toString()
      const month = (date.getMonth() + 1).toString().padStart(2, '0')
      const day = date.getDate().toString().padStart(2, '0')
      const hour = date.getHours().toString().padStart(2, '0')
      const minute = date.getMinutes().toString().padStart(2, '0')
      const second = date.getSeconds().toString().padStart(2, '0')
      const dateString = `${year}-${month}-${day}`
      const dateTimeString = `${dateString} ${hour}:${minute}:${second}`
      dateDomOptionDom.querySelector<HTMLLIElement>('li:first-child')!.innerText =
        dateString
      dateDomOptionDom.querySelector<HTMLLIElement>('li:last-child')!.innerText =
        dateTimeString
    }
    dateDomOptionDom.onmousedown = function (evt) {
      const li = evt.target as HTMLLIElement
      const dateFormat = li.dataset.format!
      dateDomOptionDom.classList.toggle('visible')
      instance.command.executeInsertElementList([
        {
          type: ElementType.DATE,
          value: '',
          dateFormat,
          valueList: [
            {
              value: li.innerText.trim()
            }
          ]
        }
      ])
    }

    const blockDom = document.querySelector<HTMLDivElement>('.menu-item__block')!
    blockDom.onclick = function () {
      console.log('block')
      new Dialog({
        title: '内容块',
        data: [
          {
            type: 'select',
            label: '类型',
            name: 'type',
            value: 'iframe',
            required: true,
            options: [
              {
                label: '网址',
                value: 'iframe'
              },
              {
                label: '视频',
                value: 'video'
              }
            ]
          },
          {
            type: 'number',
            label: '宽度',
            name: 'width',
            placeholder: '请输入宽度（默认页面内宽度）'
          },
          {
            type: 'number',
            label: '高度',
            name: 'height',
            required: true,
            placeholder: '请输入高度'
          },
          {
            type: 'input',
            label: '地址',
            name: 'src',
            required: false,
            placeholder: '请输入地址'
          },
          {
            type: 'textarea',
            label: 'HTML',
            height: 100,
            name: 'srcdoc',
            required: false,
            placeholder: '请输入HTML代码（仅网址类型有效）'
          }
        ],
        onConfirm: payload => {
          const type = payload.find(p => p.name === 'type')?.value
          if (!type) return
          const width = payload.find(p => p.name === 'width')?.value
          const height = payload.find(p => p.name === 'height')?.value
          if (!height) return
          // 地址或HTML代码至少存在一项
          const src = payload.find(p => p.name === 'src')?.value
          const srcdoc = payload.find(p => p.name === 'srcdoc')?.value
          const block: IBlock = {
            type: <BlockType>type
          }
          if (block.type === BlockType.IFRAME) {
            if (!src && !srcdoc) return
            block.iframeBlock = {
              src,
              srcdoc
            }
          } else if (block.type === BlockType.VIDEO) {
            if (!src) return
            block.videoBlock = {
              src
            }
          }
          const blockElement: IElement = {
            type: ElementType.BLOCK,
            value: '',
            height: Number(height),
            block
          }
          if (width) {
            blockElement.width = Number(width)
          }
          instance.command.executeInsertElementList([blockElement])
        }
      })
    }

    // 5. | 搜索&替换 | 打印 |
    const searchCollapseDom = document.querySelector<HTMLDivElement>(
      '.menu-item__search__collapse'
    )!
    const searchInputDom = document.querySelector<HTMLInputElement>(
      '.menu-item__search__collapse__search input'
    )!
    const replaceInputDom = document.querySelector<HTMLInputElement>(
      '.menu-item__search__collapse__replace input'
    )!
    const searchDom =
      document.querySelector<HTMLDivElement>('.menu-item__search')!
    searchDom.title = `搜索与替换(${isApple ? '⌘' : 'Ctrl'}+F)`
    const searchResultDom =
      searchCollapseDom.querySelector<HTMLLabelElement>('.search-result')!
    function setSearchResult() {
      const result = instance.command.getSearchNavigateInfo()
      if (result) {
        const { index, count } = result
        searchResultDom.innerText = `${index}/${count}`
      } else {
        searchResultDom.innerText = ''
      }
    }
    searchDom.onclick = function () {
      console.log('search')
      searchCollapseDom.style.display = 'block'
      const bodyRect = document.body.getBoundingClientRect()
      const searchRect = searchDom.getBoundingClientRect()
      const searchCollapseRect = searchCollapseDom.getBoundingClientRect()
      if (searchRect.left + searchCollapseRect.width > bodyRect.width) {
        searchCollapseDom.style.right = '0px'
        searchCollapseDom.style.left = 'unset'
      } else {
        searchCollapseDom.style.right = 'unset'
      }
      searchInputDom.focus()
    }
    searchCollapseDom.querySelector<HTMLSpanElement>('span')!.onclick =
      function () {
        searchCollapseDom.style.display = 'none'
        searchInputDom.value = ''
        replaceInputDom.value = ''
        instance.command.executeSearch(null)
        setSearchResult()
      }
    searchInputDom.oninput = function () {
      instance.command.executeSearch(searchInputDom.value || null)
      setSearchResult()
    }
    searchInputDom.onkeydown = function (evt) {
      if (evt.key === 'Enter') {
        instance.command.executeSearch(searchInputDom.value || null)
        setSearchResult()
      }
    }
    searchCollapseDom.querySelector<HTMLButtonElement>('button')!.onclick =
      function () {
        const searchValue = searchInputDom.value
        const replaceValue = replaceInputDom.value
        if (searchValue && replaceValue && searchValue !== replaceValue) {
          instance.command.executeReplace(replaceValue)
        }
      }
    searchCollapseDom.querySelector<HTMLDivElement>('.arrow-left')!.onclick =
      function () {
        instance.command.executeSearchNavigatePre()
        setSearchResult()
      }
    searchCollapseDom.querySelector<HTMLDivElement>('.arrow-right')!.onclick =
      function () {
        instance.command.executeSearchNavigateNext()
        setSearchResult()
      }

    const printDom = document.querySelector<HTMLDivElement>('.menu-item__print')!
    printDom.title = `打印(${isApple ? '⌘' : 'Ctrl'}+P)`
    printDom.onclick = function () {
      console.log('print')
      instance.command.executePrint()
    }
  
    // @ts-ignore
    docxFileInput.onchange = () => {
      const file = docxFileInput?.files?.[0];
      if (!file) return;
      const reader = new FileReader();
      reader.onload = (event) => {
        const buffer = event?.target?.result;
        if (buffer instanceof ArrayBuffer) {
          instance.command.executeImportDocx({
            arrayBuffer: buffer,
          });
        }
        docxFileInput.value = "";
      };
      reader.readAsArrayBuffer(file);
    };
  
    // excelFileInput.onchange = () => {
    //   const file = excelFileInput?.files?.[0];
    //   if (!file) return;
    //   const reader = new FileReader();
    //   reader.onload = (event) => {
    //     const buffer = event?.target?.result;
    //     if (buffer instanceof ArrayBuffer) {
    //       instance.command.executeImportExcel({
    //         arrayBuffer: buffer,
    //       });
    //     }
    //     excelFileInput.value = "";
    //   };
    //   reader.readAsArrayBuffer(file);
    // };
  });
  </script>
  
  <style>

  ul {
      list-style: none;
  }

  * {
      margin: 0;
      padding: 0;
  }

  input[type="file"] {
    display: none;
  }

  
.menu {
  width: 100%;
  height: 60px;
  top: 0;    
  left: 0;
  z-index: 9;
  position: fixed;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #F2F4F7;
  box-shadow: 0 2px 4px 0 transparent;
}

.menu-divider {
  width: 1px;
  height: 16px;
  margin: 0 8px;
  display: inline-block;
  background-color: #cfd2d8;
}

.menu-item {
  height: 24px;
  display: flex;
  align-items: center;
  position: relative;
}

.menu-item>div {
  width: 24px;
  height: 24px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 2px;
}

.menu-item>div:hover {
  background: rgba(25, 55, 88, .04);
}

.menu-item>div.active {
  background: rgba(25, 55, 88, .08);
}

.menu-item i {
  width: 16px;
  height: 16px;
  display: inline-block;
  background-repeat: no-repeat;
  background-size: 100% 100%;
}

.menu-item>div>span {
  width: 16px;
  height: 3px;
  display: inline-block;
  border: 1px solid #e2e6ed;
}

.menu-item .select {
  border: none;
  font-size: 12px;
  line-height: 24px;
  user-select: none;
}

.menu-item .select::after {
  position: absolute;
  content: "";
  top: 11px;
  width: 0;
  height: 0;
  right: 2px;
  border-color: #767c85 transparent transparent;
  border-style: solid solid none;
  border-width: 3px 3px 0;
}

.menu-item .options {
  width: 70px;
  position: absolute;
  left: 0;
  top: 25px;
  padding: 10px;
  background: #fff;
  font-size: 14px;
  box-shadow: 0 2px 12px 0 rgb(56 56 56 / 20%);
  border: 1px solid #e2e6ed;
  border-radius: 2px;
  display: none;
}

.menu-item .options.visible {
  display: block;
}

.menu-item .options li {
  padding: 5px;
  margin: 5px 0;
  user-select: none;
  transition: all .3s;
}

.menu-item .options li:hover {
  background-color: #ebecef;
}

.menu-item .options li.active {
  background-color: #e2e6ed;
}

.menu-item .menu-item__font {
  width: 65px;
  position: relative;
}

.menu-item .menu-item__size {
  width: 50px;
  text-align: center;
  position: relative;
}

.menu-item__font .select,
.menu-item__size .select {
  width: 100%;
  height: 100%;
}

.menu-item__undo.no-allow,
.menu-item__redo.no-allow,
.menu-item>div.disable {
  color: #c0c4cc;
  cursor: not-allowed;
  opacity: 0.4;
  pointer-events: none;
}

.menu-item__undo i {
  background-image: url('./assets/images/undo.svg');
}

.menu-item__redo i {
  background-image: url('./assets/images/redo.svg');
}

.menu-item__painter i {
  background-image: url('./assets/images/painter.svg');
}

.menu-item__format i {
  background-image: url('./assets/images/format.svg');
}

.menu-item__size-add i {
  background-image: url('./assets/images/size-add.svg');
}

.menu-item__size-minus i {
  background-image: url('./assets/images/size-minus.svg');
}

.menu-item__bold i {
  background-image: url('./assets/images/bold.svg');
}

.menu-item__italic i {
  background-image: url('./assets/images/italic.svg');
}

.menu-item .menu-item__underline {
  width: 30px;
  position: relative;
}

.menu-item__underline>i {
  flex-shrink: 0;
  background-image: url('./assets/images/underline.svg');
}

.menu-item__underline .select {
  width: 100%;
  height: 100%;
}

.menu-item .menu-item__underline .options {
  width: 128px;
}

.menu-item .menu-item__underline li {
  padding: 1px 5px;
}

.menu-item__underline li i {
  pointer-events: none;
}

.menu-item__underline li[data-decoration-style="solid"] {
  background-image: url('./assets/images/line-single.svg');
}

.menu-item__underline li[data-decoration-style="double"] {
  background-image: url('./assets/images/line-double.svg')
}

.menu-item__underline li[data-decoration-style="dashed"] {
  background-image: url('./assets/images/line-dash-small-gap.svg');
}

.menu-item__underline li[data-decoration-style="dotted"] {
  background-image: url('./assets/images/line-dot.svg');
}

.menu-item__underline li[data-decoration-style="wavy"] {
  background-image: url('./assets/images/line-wavy.svg');
}

.menu-item__strikeout i {
  background-image: url('./assets/images/strikeout.svg');
}

.menu-item__superscript i {
  background-image: url('./assets/images/superscript.svg');
}

.menu-item__subscript i {
  background-image: url('./assets/images/subscript.svg');
}

.menu-item__color,
.menu-item__highlight {
  display: flex;
  flex-direction: column;
}

.menu-item__color #color,
.menu-item__highlight #highlight {
  width: 1px;
  height: 1px;
  visibility: hidden;
  outline: none;
  appearance: none;
}

.menu-item__color i {
  background-image: url('./assets/images/color.svg');
}

.menu-item__color span {
  background-color: #000000;
}

.menu-item__highlight i {
  background-image: url('./assets/images/highlight.svg');
}

.menu-item__highlight span {
  background-color: #ffff00;
}

.menu-item .menu-item__title {
  width: 60px;
  position: relative;
}

.menu-item__title .select {
  width: calc(100% - 20px);
  height: 100%;
}

.menu-item__title i {
  transform: translateX(-5px);
  background-image: url('./assets/images/title.svg');
}

.menu-item__title .options {
  width: 80px;
}

.menu-item__left i {
  background-image: url('./assets/images/left.svg');
}

.menu-item__center i {
  background-image: url('./assets/images/center.svg');
}

.menu-item__right i {
  background-image: url('./assets/images/right.svg');
}

.menu-item__alignment i {
  background-image: url('./assets/images/alignment.svg');
}

.menu-item__justify i {
  background-image: url('./assets/images/justify.svg');
}

.menu-item__row-margin {
  position: relative;
}

.menu-item__row-margin i {
  background-image: url('./assets/images/row-margin.svg');
}

.menu-item__list {
  position: relative;
}

.menu-item__list i {
  background-image: url('./assets/images/list.svg');
}

.menu-item__list .options {
  width: 110px;
}

.menu-item__list .options>ul>li * {
  pointer-events: none;
}

.menu-item__list .options>ul>li li {
  margin-left: 18px;
}

.menu-item__list .options>ul>li[data-list-style='checkbox'] li::marker {
  font-size: 11px;
}

.menu-item__image i {
  background-image: url('./assets/images/image.svg');
}

.menu-item__image input {
  display: none;
}

.menu-item__table {
  position: relative;
}

.menu-item__table i {
  background-image: url('./assets/images/table.svg');
}

.menu-item .menu-item__table__collapse {
  width: 270px;
  height: 310px;
  background: #fff;
  box-shadow: 0 2px 12px 0 rgb(56 56 56 / 20%);
  border: 1px solid #e2e6ed;
  box-sizing: border-box;
  border-radius: 2px;
  position: absolute;
  display: none;
  z-index: 99;
  top: 25px;
  left: 0;
  padding: 14px 27px;
  cursor: auto;
}

.menu-item .menu-item__table__collapse .table-close {
  position: absolute;
  right: 10px;
  top: 5px;
  cursor: pointer;
}

.menu-item .menu-item__table__collapse .table-close:hover {
  color: #7d7e80;
}

.menu-item .menu-item__table__collapse:hover {
  background: #fff;
}

.menu-item .menu-item__table__collapse .table-title {
  display: flex;
  justify-content: flex-start;
  padding-bottom: 5px;
  border-bottom: 1px solid #e2e6ed;
}

.table-title span {
  font-size: 12px;
  color: #3d4757;
  display: inline;
  margin: 0;
}

.table-panel {
  cursor: pointer;
}

.table-panel .table-row {
  display: flex;
  flex-wrap: nowrap;
  margin-top: 10px;
  pointer-events: none;
}

.table-panel .table-cel {
  width: 16px;
  height: 16px;
  box-sizing: border-box;
  border: 1px solid #e2e6ed;
  background: #fff;
  position: relative;
  margin-right: 6px;
  pointer-events: none;
}

.table-panel .table-cel.active {
  border: 1px solid rgba(73, 145, 242, .2);
  background: rgba(73, 145, 242, .15);
}

.table-panel .table-row .table-cel:last-child {
  margin-right: 0;
}

.menu-item__hyperlink i {
  background-image: url('./assets/images/hyperlink.svg');
}

.menu-item__separator {
  position: relative;
}

.menu-item__separator>i {
  background-image: url('./assets/images/separator.svg');
}

.menu-item .menu-item__separator .options {
  width: 128px;
}

.menu-item .menu-item__separator li {
  padding: 1px 5px;
}

.menu-item__separator li i {
  pointer-events: none;
}

.menu-item__separator li[data-separator="0,0"] {
  background-image: url('./assets/images/line-single.svg');
}

.menu-item__separator li[data-separator="1,1"] {
  background-image: url('./assets/images/line-dot.svg');
}

.menu-item__separator li[data-separator="3,1"] {
  background-image: url('./assets/images/line-dash-small-gap.svg');
}

.menu-item__separator li[data-separator="4,4"] {
  background-image: url('./assets/images/line-dash-large-gap.svg');
}

.menu-item__separator li[data-separator="7,3,3,3"] {
  background-image: url('./assets/images/line-dash-dot.svg');
}

.menu-item__separator li[data-separator="6,2,2,2,2,2"] {
  background-image: url('./assets/images/line-dash-dot-dot.svg');
}

.menu-item__watermark>i {
  background-image: url('./assets/images/watermark.svg');
}

.menu-item__watermark {
  position: relative;
}

.menu-item__codeblock i {
  background-image: url('./assets/images/codeblock.svg');
}

.menu-item__page-break i {
  background-image: url('./assets/images/page-break.svg');
}

.menu-item__control {
  position: relative;
}

.menu-item__control i {
  background-image: url('./assets/images/control.svg');
}

.menu-item__checkbox i {
  background-image: url('./assets/images/checkbox.svg');
}

.menu-item__radio i {
  background-image: url('./assets/images/radio.svg');
}

.menu-item__latex i {
  background-image: url('./assets/images/latex.svg');
}

.menu-item__date {
  position: relative;
}

.menu-item__date i {
  background-image: url('./assets/images/date.svg');
}

.menu-item__date .options {
  width: 160px;
}

.menu-item__block i {
  background-image: url('./assets/images/block.svg');
}

.menu-item .menu-item__control .options {
  width: 55px;
}

.menu-item__search {
  position: relative;
}

.menu-item__search i {
  background-image: url('./assets/images/search.svg');
}

.menu-item .menu-item__search__collapse {
  width: 260px;
  height: 72px;
  box-sizing: border-box;
  position: absolute;
  display: none;
  z-index: 99;
  top: 25px;
  left: 0;
  background: #ffffff;
  box-shadow: 0px 5px 5px #e3dfdf;
}

.menu-item .menu-item__search__collapse:hover {
  background: #ffffff;
}

.menu-item .menu-item__search__collapse>div {
  width: 250px;
  height: 36px;
  padding: 0 5px;
  line-height: 36px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-radius: 4px;
}

.menu-item .menu-item__search__collapse>div input {
  width: 205px;
  height: 27px;
  appearance: none;
  background-color: #fff;
  background-image: none;
  border-radius: 4px;
  border: 1px solid #ebebeb;
  box-sizing: border-box;
  color: #606266;
  display: inline-block;
  line-height: 27px;
  outline: none;
  padding: 0 5px;
}

.menu-item .menu-item__search__collapse>div span {
  height: 100%;
  color: #dcdfe6;
  font-size: 25px;
  display: inline-block;
  border: 0;
  padding: 0 10px;
}

.menu-item .menu-item__search__collapse__replace button {
  display: inline-block;
  border: 1px solid #e2e6ed;
  border-radius: 2px;
  background: #fff;
  line-height: 22px;
  padding: 0 6px;
  white-space: nowrap;
  margin-left: 4px;
  cursor: pointer;
  font-size: 12px;
}

.menu-item .menu-item__search__collapse__replace button:hover {
  background: rgba(25, 55, 88, .04);
}

.menu-item .menu-item__search__collapse__search {
  position: relative;
}

.menu-item .menu-item__search__collapse__search label {
  right: 110px;
  font-size: 12px;
  color: #3d4757;
  position: absolute;
}

.menu-item .menu-item__search__collapse__search>input {
  padding: 5px 90px 5px 5px !important;
}

.menu-item .menu-item__search__collapse__search>div {
  width: 28px;
  height: 27px;
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  border-left: 1px solid #e2e6ed;
  transition: all .5s;
}

.menu-item .menu-item__search__collapse__search>div:hover {
  background-color: rgba(25, 55, 88, .04);
}

.menu-item .menu-item__search__collapse__search i {
  width: 6px;
  height: 8px;
  transform: translateY(1px);
}

.menu-item .menu-item__search__collapse__search .arrow-left {
  right: 76px;
}

.menu-item .menu-item__search__collapse__search .arrow-left i {
  background: url(./assets/images/arrow-left.svg) no-repeat;
}

.menu-item .menu-item__search__collapse__search .arrow-right {
  right: 48px;
}

.menu-item .menu-item__search__collapse__search .arrow-right i {
  background: url(./assets/images/arrow-right.svg) no-repeat;
}

.menu-item__print i {
  background-image: url('./assets/images/print.svg');
}

p > img {
  min-width: 100px;
  min-height: 100px;
}

  </style>
  